#!/usr/bin/env python2
#-*- coding: utf-8 -*-

import os
import re
import sys
import json
import logging
import copy
import time
import traceback

from datetime import datetime

from sqlalchemy import text

from Ump import utils
from Ump.common import log
from Ump.common import exception 
from Ump.objs.session_wrapper import _sw
from Ump.objs.db import models
from Ump.objs.manager_base import Manager
from Ump.objs.session_wrapper import enable_log_and_session, _sw

from Ump.schedule.api import ScheduleApi


schedule_api = ScheduleApi()
LOG = log.get_log('Ump.objs.schedule.manager')

INTERVAL_MODEL = { 
    "schedule_type": 'interval',
    "every": 1,
    "period": "minutes",
#    "start_date": utils.timenow() + utils.timedelta(seconds=30),
}   

CRON_MODEL = {
    'schedule_type': 'cron',
    'second': 0,
    'minute': 0,
    'hour': 0,
    'day': 0,
    'month': 0,
    'year': 0,
}

ZERO_CRONTAB_MODEL = {
    "schedule_type": 'cron',
    "second": 0,
    "minute": 0,
    "hour": 0, 
}

class ScheduleManager(Manager):

    def __init__(self):
        self.super_ = super(ScheduleManager, self)
        self.super_.__init__()

    @enable_log_and_session(resource='settings', event='update',  disable_oplog=True)
    def update(self, _logger, kwargs):
        schedule_id = kwargs.get('id')
        schedule = _sw.get_one(models.ScheduleJob, schedule_id)
        if not schedule:
            raise exception.NotFound(_id=schedule_id)

        schedule = self._update(schedule, **kwargs)

        return schedule

    def _update(self, schedule, value=None, **kwargs):

        values = {}
        false_list = ['false', 'False', False]
        enabled = False if kwargs.get('enabled')  in false_list else True
        utils.update_values(values, 'enabled', enabled)
        
        return schedule_api.update_job(schedule.id, values)

    def init_schedule(self):
        schedule_api = ScheduleApi(is_op_schedule=False)

        self._init_interval_schedule_seconds(schedule_api)

        self._init_interval_schedule_test(schedule_api)
        #self._init_interval_schedule(schedule_api)
        # self._init_crontab_schedule(schedule_api)

    def _init_interval_schedule_seconds(self, schedule_api):
        class_names = [('TaskTimeoutJob', 30), ('VolumeUsedSyncJob', 30),
                       ('NodeSyncJob', 30), ('VolumeAutoDeleteExpungeJob', 86400)]
        for info in class_names:        
            class_name = info[0]
            every = info[1]
            if _sw.get_one(models.ScheduleJob, id_or_spec={'class_name': class_name}):
                continue

            interval_model = copy.deepcopy(INTERVAL_MODEL) 
            interval_model['class_name'] = class_name
            interval_model['every'] = every 
            interval_model['period'] = 'seconds' 
            schedule_api.create_job(interval_model)

    def _init_interval_schedule_test(self, schedule_api):
        class_names = [('HostSyncJob', 1), ('VolumeConnectionsSyncJob', 1), 
            ('SnapshotManagerJob', 1), ('LatencySyncJob', 5), ('LichSyslogMonitor', 1), 
            ('IopsSyncJob', 5), ('UmpDaySyncJob', 60)]
    
        for info in class_names:        
            class_name = info[0]
            every = info[1]
            if _sw.get_one(models.ScheduleJob, id_or_spec={'class_name': class_name}):
                continue

            interval_model = copy.deepcopy(INTERVAL_MODEL) 
            interval_model['class_name'] = class_name
            interval_model['every'] = every 
            schedule_api.create_job(interval_model)
        
        class_names = ['LicenseJob', 'UmpCleanJob', 'CallhomeJob']
        for class_name in class_names:
            if _sw.get_one(models.ScheduleJob, id_or_spec={'class_name': class_name}):
                continue

            CRON_MODEL['class_name'] = class_name
            if class_name in ['CallhomeJob']:
                CRON_MODEL['hour'] = 6

            schedule_api.create_job(CRON_MODEL)


    @staticmethod
    def init_backup_job_schedule():
        schedule_api = ScheduleApi(False)
        values = {
            "schedule_type": 'interval',
            "every": 1,
            "period": "hours",
            'class_name': 'BackupJob',
        }
        if not _sw.get_one(models.ScheduleJob, id_or_spec={'class_name': 'BackupJob'}):
            schedule_api.create_job(values)

    def _get_one_with_name(self, class_name):
        job = _sw.get_one(models.ScheduleJob, id_or_spec={'class_name': class_name})
        return job

    @enable_log_and_session(resource='settings', event='update', disable_oplog=True)
    def job_create(self, _logger, params):
        """
        This method is used to allow user to create schedule job of customized statistics table.
        :param params: get from web forms from user
        """
        report_name = params.get('report_name')
        start_time = params.get('start_time')
        end_time = params.get('end_time')
        interval_time = params.get('interval_time')
        username = params.get('username')
        report_type = params.get('report_type')
        type_id = params.get('type_id')
        type_name = params.get('type_name')

        if not report_name:
            raise exception.UnknownParameter

        if _sw.get_one(models.ScheduleJob, id_or_spec={'name': report_name}):
            raise exception.PoolFound("The report name is already existed!")

        if not interval_time:
            raise exception.UnknownParameter

        if not type_id:
            raise exception.InvalidParameter("Type name can not be none!")

        if not report_type:
            raise exception.InvalidParameter("Report type can not be none!")

        if int(interval_time) % 5:
            raise exception.InvalidParameter("interval time should be the multiple of 5 minute!")
        if start_time > end_time:
            raise exception.InvalidParameter("end time should be larger than start time!")

        context = {
            'report_name': report_name,
            'report_type': report_type,
            'type_id': type_id,
            'type_name': type_name,
            'start_time': start_time,
            'end_time': end_time,
            'interval_time': interval_time,
            'owner': username,
        }
        #run_date = datetime.datetime.strptime('2016-12-2 14:20:20', '%Y-%m-%d %H:%M:%S')
        run_date = utils.str2date(end_time)
        values = {
            'name': report_name,
            'schedule_type': 'date',
            'class_name': 'ReportIopsJob',
            'owner': username,
            'run_date': run_date,
            'context': json.dumps(context),
            'user_id': _sw.get_user_id(username),
            'status': 'not finished',
        }

        return schedule_api.create_job(values)

    def job_delete(self, params):
        job_id = params.get('id')
        job = _sw.get_one(models.ScheduleJob, id_or_spec=job_id)
        if not job:
            raise exception.ScheduleJobNotFound('cannot found')

        return schedule_api.delete_job(job.id)

    def report_delete(self, params):
        report_id = params.get('id')
        report = _sw.get_one(models.ScheduleJobReport, id_or_spec=report_id)
        if not report:
            raise exception.NotFound('cannot found')

        report.delete()


if __name__ == '__main__':
    snm = ScheduleManager()
    snm.create()
    snm.update()
